! Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
! See https://llvm.org/LICENSE.txt for license information.
! SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception


module shape_arr
    implicit none
    contains
     subroutine assign_value(l_idx, u_idx, arr, res)
         implicit none
         integer, intent(in) :: l_idx, u_idx
         real(kind=16), dimension(:,:), intent(in) :: arr
         real(kind=16), dimension(:), intent(inout) :: res
         real(kind=16), dimension(u_idx - l_idx + 1) :: arra
         arra = reshape(arr, (/ u_idx - l_idx + 1 /))
         res(l_idx:u_idx) = arra
     end subroutine
end module

! Program to test for runtime library MATMUL routines.
program mnaxtb
    use shape_arr
    use check_mod
    implicit none
    integer, parameter :: n_extent = 20
    integer, parameter :: m_extent = 15
    integer, parameter :: k_extent = 20
    integer, parameter :: mn_extent = 15
    integer, parameter :: mm_extent = 15
    integer, parameter :: mk_extent = 20
    integer, parameter :: sn_extent = 5
    integer, parameter :: sm_extent = 5
    integer, parameter :: sk_extent = 6
    integer, parameter :: length = 730
    
    real(kind=16), dimension(n_extent, m_extent) :: arr1
    real(kind=16), dimension(k_extent, m_extent) :: arr2
    real(kind=16), dimension(n_extent, k_extent) :: arr3
    real(kind=16), dimension(mn_extent, mk_extent) :: arr4
    real(kind=16), dimension(sn_extent, sk_extent) :: arr5
    real(kind=16), dimension(length) :: result, expect
    integer :: i, j, k
    
    
    do i = 1, m_extent
       do j = 1, n_extent
          arr1(j, i) = 1.0_16 * abs(j - 10)
       end do
       do k = 1, k_extent
          arr2(k, i) = 2.0_16 * abs(k - 10)
       end do
    end do
    
    expect=(/ 2430.0_16, 2160.0_16, 1890.0_16, 1620.0_16, 1350.0_16, 1080.0_16,  810.0_16,  540.0_16,  270.0_16,    0.0_16, &
               270.0_16,  540.0_16,  810.0_16, 1080.0_16, 1350.0_16, 1620.0_16, 1890.0_16, 2160.0_16, 2430.0_16, 2700.0_16, &
              2160.0_16, 1920.0_16, 1680.0_16, 1440.0_16, 1200.0_16,  960.0_16,  720.0_16,  480.0_16,  240.0_16,    0.0_16, &
               240.0_16,  480.0_16,  720.0_16,  960.0_16, 1200.0_16, 1440.0_16, 1680.0_16, 1920.0_16, 2160.0_16, 2400.0_16, &
              1890.0_16, 1680.0_16, 1470.0_16, 1260.0_16, 1050.0_16,  840.0_16,  630.0_16,  420.0_16,  210.0_16,    0.0_16, &
               210.0_16,  420.0_16,  630.0_16,  840.0_16, 1050.0_16, 1260.0_16, 1470.0_16, 1680.0_16, 1890.0_16, 2100.0_16, &
              1620.0_16, 1440.0_16, 1260.0_16, 1080.0_16,  900.0_16,  720.0_16,  540.0_16,  360.0_16,  180.0_16,    0.0_16, &
               180.0_16,  360.0_16,  540.0_16,  720.0_16,  900.0_16, 1080.0_16, 1260.0_16, 1440.0_16, 1620.0_16, 1800.0_16, &
              1350.0_16, 1200.0_16, 1050.0_16,  900.0_16,  750.0_16,  600.0_16,  450.0_16,  300.0_16,  150.0_16,    0.0_16, &
               150.0_16,  300.0_16,  450.0_16,  600.0_16,  750.0_16,  900.0_16, 1050.0_16, 1200.0_16, 1350.0_16, 1500.0_16, &
              1080.0_16,  960.0_16,  840.0_16,  720.0_16,  600.0_16,  480.0_16,  360.0_16,  240.0_16,  120.0_16,    0.0_16, &
               120.0_16,  240.0_16,  360.0_16,  480.0_16,  600.0_16,  720.0_16,  840.0_16,  960.0_16, 1080.0_16, 1200.0_16, &
               810.0_16,  720.0_16,  630.0_16,  540.0_16,  450.0_16,  360.0_16,  270.0_16,  180.0_16,   90.0_16,    0.0_16, &
                90.0_16,  180.0_16,  270.0_16,  360.0_16,  450.0_16,  540.0_16,  630.0_16,  720.0_16,  810.0_16,  900.0_16, &
               540.0_16,  480.0_16,  420.0_16,  360.0_16,  300.0_16,  240.0_16,  180.0_16,  120.0_16,   60.0_16,    0.0_16, &
                60.0_16,  120.0_16,  180.0_16,  240.0_16,  300.0_16,  360.0_16,  420.0_16,  480.0_16,  540.0_16,  600.0_16, &
               270.0_16,  240.0_16,  210.0_16,  180.0_16,  150.0_16,  120.0_16,   90.0_16,   60.0_16,   30.0_16,    0.0_16, &
                30.0_16,   60.0_16,   90.0_16,  120.0_16,  150.0_16,  180.0_16,  210.0_16,  240.0_16,  270.0_16,  300.0_16, &
                 0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16, &
                 0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16, &
               270.0_16,  240.0_16,  210.0_16,  180.0_16,  150.0_16,  120.0_16,   90.0_16,   60.0_16,   30.0_16,    0.0_16, &
                30.0_16,   60.0_16,   90.0_16,  120.0_16,  150.0_16,  180.0_16,  210.0_16,  240.0_16,  270.0_16,  300.0_16, &
               540.0_16,  480.0_16,  420.0_16,  360.0_16,  300.0_16,  240.0_16,  180.0_16,  120.0_16,   60.0_16,    0.0_16, &
                60.0_16,  120.0_16,  180.0_16,  240.0_16,  300.0_16,  360.0_16,  420.0_16,  480.0_16,  540.0_16,  600.0_16, &
               810.0_16,  720.0_16,  630.0_16,  540.0_16,  450.0_16,  360.0_16,  270.0_16,  180.0_16,   90.0_16,    0.0_16, &
                90.0_16,  180.0_16,  270.0_16,  360.0_16,  450.0_16,  540.0_16,  630.0_16,  720.0_16,  810.0_16,  900.0_16, &
              1080.0_16,  960.0_16,  840.0_16,  720.0_16,  600.0_16,  480.0_16,  360.0_16,  240.0_16,  120.0_16,    0.0_16, &
               120.0_16,  240.0_16,  360.0_16,  480.0_16,  600.0_16,  720.0_16,  840.0_16,  960.0_16, 1080.0_16, 1200.0_16, &
              1350.0_16, 1200.0_16, 1050.0_16,  900.0_16,  750.0_16,  600.0_16,  450.0_16,  300.0_16,  150.0_16,    0.0_16, &
               150.0_16,  300.0_16,  450.0_16,  600.0_16,  750.0_16,  900.0_16, 1050.0_16, 1200.0_16, 1350.0_16, 1500.0_16, &
              1620.0_16, 1440.0_16, 1260.0_16, 1080.0_16,  900.0_16,  720.0_16,  540.0_16,  360.0_16,  180.0_16,    0.0_16, &
               180.0_16,  360.0_16,  540.0_16,  720.0_16,  900.0_16, 1080.0_16, 1260.0_16, 1440.0_16, 1620.0_16, 1800.0_16, &
              1890.0_16, 1680.0_16, 1470.0_16, 1260.0_16, 1050.0_16,  840.0_16,  630.0_16,  420.0_16,  210.0_16,    0.0_16, &
               210.0_16,  420.0_16,  630.0_16,  840.0_16, 1050.0_16, 1260.0_16, 1470.0_16, 1680.0_16, 1890.0_16, 2100.0_16, &
              2160.0_16, 1920.0_16, 1680.0_16, 1440.0_16, 1200.0_16,  960.0_16,  720.0_16,  480.0_16,  240.0_16,    0.0_16, &
               240.0_16,  480.0_16,  720.0_16,  960.0_16, 1200.0_16, 1440.0_16, 1680.0_16, 1920.0_16, 2160.0_16, 2400.0_16, &
              2430.0_16, 2160.0_16, 1890.0_16, 1620.0_16, 1350.0_16, 1080.0_16,  810.0_16,  540.0_16,  270.0_16,    0.0_16, &
               270.0_16,  540.0_16,  810.0_16, 1080.0_16, 1350.0_16, 1620.0_16, 1890.0_16, 2160.0_16, 2430.0_16, 2700.0_16, &
              2700.0_16, 2400.0_16, 2100.0_16, 1800.0_16, 1500.0_16, 1200.0_16,  900.0_16,  600.0_16,  300.0_16,    0.0_16, &
               300.0_16,  600.0_16,  900.0_16, 1200.0_16, 1500.0_16, 1800.0_16, 2100.0_16, 2400.0_16, 2700.0_16, 3000.0_16, &
              2430.0_16, 2160.0_16, 1890.0_16, 1620.0_16, 1350.0_16, 1080.0_16,  810.0_16,  540.0_16,  270.0_16,    0.0_16, &
               270.0_16,  540.0_16,  810.0_16, 1080.0_16, 1350.0_16, 2160.0_16, 1920.0_16, 1680.0_16, 1440.0_16, 1200.0_16, &
               960.0_16,  720.0_16,  480.0_16,  240.0_16,    0.0_16,  240.0_16,  480.0_16,  720.0_16,  960.0_16, 1200.0_16, &
              1890.0_16, 1680.0_16, 1470.0_16, 1260.0_16, 1050.0_16,  840.0_16,  630.0_16,  420.0_16,  210.0_16,    0.0_16, &
               210.0_16,  420.0_16,  630.0_16,  840.0_16, 1050.0_16, 1620.0_16, 1440.0_16, 1260.0_16, 1080.0_16,  900.0_16, &
               720.0_16,  540.0_16,  360.0_16,  180.0_16,    0.0_16,  180.0_16,  360.0_16,  540.0_16,  720.0_16,  900.0_16, &
              1350.0_16, 1200.0_16, 1050.0_16,  900.0_16,  750.0_16,  600.0_16,  450.0_16,  300.0_16,  150.0_16,    0.0_16, &
               150.0_16,  300.0_16,  450.0_16,  600.0_16,  750.0_16, 1080.0_16,  960.0_16,  840.0_16,  720.0_16,  600.0_16, &
               480.0_16,  360.0_16,  240.0_16,  120.0_16,    0.0_16,  120.0_16,  240.0_16,  360.0_16,  480.0_16,  600.0_16, &
               810.0_16,  720.0_16,  630.0_16,  540.0_16,  450.0_16,  360.0_16,  270.0_16,  180.0_16,   90.0_16,    0.0_16, &
                90.0_16,  180.0_16,  270.0_16,  360.0_16,  450.0_16,  540.0_16,  480.0_16,  420.0_16,  360.0_16,  300.0_16, &
               240.0_16,  180.0_16,  120.0_16,   60.0_16,    0.0_16,   60.0_16,  120.0_16,  180.0_16,  240.0_16,  300.0_16, &
               270.0_16,  240.0_16,  210.0_16,  180.0_16,  150.0_16,  120.0_16,   90.0_16,   60.0_16,   30.0_16,    0.0_16, &
                30.0_16,   60.0_16,   90.0_16,  120.0_16,  150.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16, &
                 0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16,    0.0_16, &
               270.0_16,  240.0_16,  210.0_16,  180.0_16,  150.0_16,  120.0_16,   90.0_16,   60.0_16,   30.0_16,    0.0_16, &
                30.0_16,   60.0_16,   90.0_16,  120.0_16,  150.0_16,  540.0_16,  480.0_16,  420.0_16,  360.0_16,  300.0_16, &
               240.0_16,  180.0_16,  120.0_16,   60.0_16,    0.0_16,   60.0_16,  120.0_16,  180.0_16,  240.0_16,  300.0_16, &
               810.0_16,  720.0_16,  630.0_16,  540.0_16,  450.0_16,  360.0_16,  270.0_16,  180.0_16,   90.0_16,    0.0_16, &
                90.0_16,  180.0_16,  270.0_16,  360.0_16,  450.0_16, 1080.0_16,  960.0_16,  840.0_16,  720.0_16,  600.0_16, &
               480.0_16,  360.0_16,  240.0_16,  120.0_16,    0.0_16,  120.0_16,  240.0_16,  360.0_16,  480.0_16,  600.0_16, &
              1350.0_16, 1200.0_16, 1050.0_16,  900.0_16,  750.0_16,  600.0_16,  450.0_16,  300.0_16,  150.0_16,    0.0_16, &
               150.0_16,  300.0_16,  450.0_16,  600.0_16,  750.0_16, 1620.0_16, 1440.0_16, 1260.0_16, 1080.0_16,  900.0_16, &
               720.0_16,  540.0_16,  360.0_16,  180.0_16,    0.0_16,  180.0_16,  360.0_16,  540.0_16,  720.0_16,  900.0_16, &
              1890.0_16, 1680.0_16, 1470.0_16, 1260.0_16, 1050.0_16,  840.0_16,  630.0_16,  420.0_16,  210.0_16,    0.0_16, &
               210.0_16,  420.0_16,  630.0_16,  840.0_16, 1050.0_16, 2160.0_16, 1920.0_16, 1680.0_16, 1440.0_16, 1200.0_16, &
               960.0_16,  720.0_16,  480.0_16,  240.0_16,    0.0_16,  240.0_16,  480.0_16,  720.0_16,  960.0_16, 1200.0_16, &
              2430.0_16, 2160.0_16, 1890.0_16, 1620.0_16, 1350.0_16, 1080.0_16,  810.0_16,  540.0_16,  270.0_16,    0.0_16, &
               270.0_16,  540.0_16,  810.0_16, 1080.0_16, 1350.0_16, 2700.0_16, 2400.0_16, 2100.0_16, 1800.0_16, 1500.0_16, &
              1200.0_16,  900.0_16,  600.0_16,  300.0_16,    0.0_16,  300.0_16,  600.0_16,  900.0_16, 1200.0_16, 1500.0_16, &
               810.0_16,  720.0_16,  630.0_16,  540.0_16,  450.0_16,  720.0_16,  640.0_16,  560.0_16,  480.0_16,  400.0_16, &
               630.0_16,  560.0_16,  490.0_16,  420.0_16,  350.0_16,  540.0_16,  480.0_16,  420.0_16,  360.0_16,  300.0_16, &
               450.0_16,  400.0_16,  350.0_16,  300.0_16,  250.0_16,  360.0_16,  320.0_16,  280.0_16,  240.0_16,  200.0_16 /)


    arr3 = 0.0_16
    arr3 = matmul(arr1, transpose(arr2))
    call assign_value(1, 400, arr3, result)
    
    arr4 = 0.0_16
    arr4 = matmul(arr1(1:mn_extent, 1:mm_extent), transpose(arr2(1:mk_extent, 1:mm_extent)))
    call assign_value(401, 700, arr4, result)
    
    arr5 = 0.0_16
    arr5 = matmul(arr1(1:sn_extent, 1:sm_extent), transpose(arr2(1:sk_extent, 1:sm_extent)))
    call assign_value(701, 730, arr5, result)

    call checkr16(result, expect, length)
end program
